package com.uwo.house.controller;

import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.uwo.house.beans.PayLogEntity;
import com.uwo.house.beans.WeixinConfig;
import com.uwo.house.beans.response.BillResp;
import com.uwo.house.service.serviceImpl.AdministratorService;
import com.uwo.house.service.serviceImpl.AliPayService;
import com.uwo.house.service.serviceImpl.OrderMeasureService;
import com.uwo.house.util.RandChars;
import com.uwo.house.util.StringUtil;
import com.uwo.house.util.UtilReturn;
import com.uwo.house.util.WeiXinSign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by cynic on 2017/12/6.
 */
@Controller
@RequestMapping("/weixinpay")
public class WeChatPayController extends BaseController{
    @Autowired
    AliPayService aliPayService;
    @Autowired
    OrderMeasureService orderMeasureService;
    @Autowired
    AdministratorService administratorService;

    /**
     * 统一下单，并生成微信支付二维码
     *
     * @return
     */
    @RequestMapping(value = "/weixinunifiedorder")
    @ResponseBody
    public Map weixinUnifiedOrder(HttpServletRequest request, HttpServletResponse response) {
        try {
            String orderId = request.getParameter("orderId");//订单号
            String body = "预约量房";
            PayLogEntity payLogEntity = aliPayService.getPayLogByOrderNo(orderId);
            String payLogId = payLogEntity.getId();//商品id
            //金额
            BigDecimal price = payLogEntity.getPayShouldPrice();
            double final_price = price.doubleValue() * 100;
            //微信金额需要整型
            Integer total_fee = (int) final_price;
            if (!StringUtil.isEmpty(orderId) && !StringUtil.isEmpty(body) && !StringUtil.isEmpty(payLogId)) {
                WeixinConfig config = new WeixinConfig();
                WXPay wxpay = new WXPay(config);
                String appid = config.getAppID();//appid
                String mch_id = config.getMchID();//mch_id
                //设置参数
                Map<String, String> data = new HashMap<String, String>();
                data.put("appid", appid);
                data.put("mch_id", mch_id);
                data.put("nonce_str", RandChars.getRandomString(16));//随机字符串
                data.put("body", body);//商品描述
                data.put("out_trade_no", orderId);//商户订单号
                //默认人民币：CNY
                data.put("fee_type", "CNY");//符合ISO 4217标准的三位字母代码，
                data.put("total_fee", total_fee.toString());//标价金额，订单总金额，单位为：分！
                String ip = request.getHeader("x-forwarded-for");
                data.put("spbill_create_ip", "127.0.0.1");//终端IP，APP和网页支付提交用户端ip
                data.put("notify_url", "http://122.237.100.110:80/uwo-house/weixinpay/weixinpaynotifyurl");//通知地址
                data.put("trade_type", "NATIVE");//此处指定为扫码支付
                data.put("product_id", payLogId);//此参数为二维码中包含的商品ID，商户自行定义
                String sign = WeiXinSign.generateSignature(data, config.getKey());
                data.put("sign", sign);//签名
                Map<String, String> resp = wxpay.unifiedOrder(data);
                if (resp.get("return_code").equals("SUCCESS") && resp.get("result_code").equals("SUCCESS")) {
                    return UtilReturn.resSuccesssMap(UtilReturn.SUCCESS_CODE, UtilReturn.SUCCESS_MESSAGE, resp);
                } else {
                    return UtilReturn.resErrorMap("统一下单失败", UtilReturn.ERROR_CODE);
                }
            } else {
                return UtilReturn.resErrorMap("参数错误", UtilReturn.ERROR_CODE);
            }
        } catch (Exception e) {
            return UtilReturn.resErrorMap("统一下单失败", UtilReturn.ERROR_CODE);
        }
    }

    /**
     * App支付完后，调用的回调函数
     *
     * @return
     */
    @RequestMapping(value = "/weixinpaynotifyurl", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void weixinPayNotifyUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            //读取参数
            InputStream inputStream;
            StringBuffer sb = new StringBuffer();
            inputStream = request.getInputStream();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();

            // 支付结果通知的xml格式数据，具体的需要根据实际的情况看，先放着
            String notifyData = sb.toString();
            WeixinConfig config = new WeixinConfig();
//            WXPay wxpay = new WXPay(config);
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
            //商户订单号 pay_log中的orderno
            String out_trade_no = notifyMap.get("out_trade_no");
            //微信支付订单号
            String transaction_id = notifyMap.get("transaction_id");
            //订单金额
            String total_fee = notifyMap.get("total_fee");
            //判断返回值是否是 SUCCESS
            if (notifyMap.get("return_code").equals("SUCCESS")) {
                //判断签名是否正确
                if (WXPayUtil.isSignatureValid(notifyMap, config.getKey())) {
                    //业务逻辑
                    //成功支付更新交易记录表(PAY_LOG)信息
                    PayLogEntity payLogEntity = aliPayService.getPayLogByOrderNo(out_trade_no);
                    //处理自己的业务逻辑
                    if ("1".equals(payLogEntity.getPayFlag())) {
                        response.getWriter().write(setXml("SUCCESS", "订单已经支付"));//告诉微信已经收到通知了
                    } else {
                        payLogEntity.setTradeNo(transaction_id);//微信交易号
                        payLogEntity.setPayPrice(new BigDecimal(div(Double.valueOf(total_fee),100.00,2)));//支付金额
                        payLogEntity.setPayFlag("1");//支付状态:1已支付
                        payLogEntity.setPayTime(new Date());//支付时间
                        payLogEntity.setPayType("2");//微信支付
                        aliPayService.updatePayLog(payLogEntity);
                        this.orderMeasureService.addOrder(out_trade_no);//添加订单信息(order_status表)
                        String userId = orderMeasureService.getUserIdByOrderId(out_trade_no);//获取用户id
                        this.addRecord("我的新房预约了测量", userId, "", "");
                        BillResp billResp = new BillResp();
                        billResp.setAmount(new BigDecimal(div(Double.valueOf(total_fee),100,2)));
                        billResp.setCreateTime(new Date());
                        billResp.setIdentification("1");
                        billResp.setType("1");
                        billResp.setOrderId(out_trade_no);
                        billResp.setPayType("2");//微信支付
                        administratorService.addBillLog(billResp);//添加账目信息
                        response.getWriter().write(setXml("SUCCESS", "OK"));
                    }
                } else {
                    response.getWriter().write(setXml("FAIL ", "签名不正确"));
                }
            } else {
                response.getWriter().write(setXml("FAIL ", notifyMap.get("return_msg")));
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().write(setXml("FAIL ", e.getMessage()));
        }
    }

    /**
     * 轮询函数 判断是否支付成功
     *
     * @return
     */
    @RequestMapping(value = "/getpayinfo", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Map getPayInfo(String orderNo) throws IOException {
        PayLogEntity payLogEntity = aliPayService.getPayLogByOrderNo(orderNo);
        if ("1".equals(payLogEntity.getPayFlag())) {
            return UtilReturn.resSuccesssMap(UtilReturn.SUCCESS_CODE, UtilReturn.SUCCESS_MESSAGE, "已经支付成功");
        } else {
            return UtilReturn.resErrorMap("未支付", UtilReturn.ERROR_CODE);
        }
    }

    public static String setXml(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }

    /**
     * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指
     * 定精度，以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1,double v2,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }
}
